package com.uzai.console.web.wechatminipro;

import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.qiniu.util.UrlUtils;
import com.uzai.console.common.utils.WXXmlToMapUtil;
import com.uzai.console.common.utils.aes.WXBizMsgCrypt;
import com.uzai.console.config.UzaiConsoleSysConfig;
import com.uzai.console.constant.CacheKey;
import com.uzai.console.constant.CommonConstant;
import com.uzai.console.constant.Const;
import com.uzai.console.dto.wechatminipro.WechatMiniProDto;
import com.uzai.console.web.BaseController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@Api(value = "小程序授权回调函数", tags = "淘宝|淘宝联盟", hidden = true)
@ApiSort(9)
@RestController
public class WechatMiniProAuthController extends BaseController {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UzaiConsoleSysConfig uzaiConsoleSysConfig;


    private Logger logger = LoggerFactory.getLogger(WechatMiniProAuthController.class);

    /**
     * 小程序第三方平台 回调处理
     */
    @ApiOperation(value = "小程序第三方平台回调", hidden = true)
    @GetMapping("/wx/callback")
    public Object componentVerifyTicket(HttpServletRequest request, HttpServletResponse response) {
        logger.info("componentVerifyTicket --------- " );
        try {
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            // 微信加密签名
            String msgSignature = request.getParameter("msg_signature");
            // 时间戳
            String timeStamp = request.getParameter("timestamp");
            // 随机数
            String nonce = request.getParameter("nonce");
            String encryptType = request.getParameter("encrypt_type");
            String signature = request.getParameter("signature");
            logger.info(String.format("componentVerifyTicket req ,{}, {}, {}, {}, {}", msgSignature, timeStamp, nonce, encryptType, signature));
            // 从请求中读取整个post数据
            InputStream inputStream;
            String postData = null;
            inputStream = request.getInputStream();
            postData = IOUtils.toString(inputStream, "utf-8");
            WXBizMsgCrypt wxBizMsgCrypt = new WXBizMsgCrypt(uzaiConsoleSysConfig.getWxminiproToken(), uzaiConsoleSysConfig.getWxminiproAesKey(), uzaiConsoleSysConfig.getWxminiproAppId());
            String msg = wxBizMsgCrypt.decryptMsg(msgSignature, timeStamp, nonce, postData);
            logger.info("wechat return msg : {}" , msg);
            // 将xml转为map
            Map<String, String> result = WXXmlToMapUtil.xmlToMap(msg);
            String infotype = result.get("InfoType");
            logger.info("call back infotype : {}", infotype);
            switch (infotype) {
                case "component_verify_ticket":   //接收票据 【component_verify_ticket】
                    String ComponentVerifyTicket = result.get("ComponentVerifyTicket");
                    String componentAppId = result.get("AppId");
                    logger.info(" component_verify_ticket :{} , appId : {}" ,ComponentVerifyTicket,componentAppId);
                    // 缓存 ticket
                    redisTemplate.opsForValue().set(String.format(CacheKey.WX_PLATFORM_TICKET,componentAppId), ComponentVerifyTicket,12, TimeUnit.HOURS);
                   //  存数据库
                    logger.info("component_verify_ticket : {}", ComponentVerifyTicket);
                    break;
                case "authorized": //授权成功
                    //获取商户id ,查询商户appid
                    //Long merchantId = Long.parseLong(request.getParameter("state"));
                    String appId = request.getParameter("appid");
                    String code = request.getParameter("code");
                    redisTemplate.opsForValue().set(String.format(CacheKey.WX_AUTH_CODE,appId), code,12, TimeUnit.HOURS);

                    //查询商户appid进行 绑定 并标记为已完成授权状态数据 .
                    //缓存ticket数据到 第三方平台 .
                    //this.disposeAuthResult(result);
                    logger.info("auth success");
                    break;
                case "unauthorized"://用户取消授权
//                    String authorizerAppId = result.get();
//                    customerMpDao.updateAuthorizationFlag(authorizerAppId);
//                    this.disposeAuthResult(result);
                    logger.info("remove auth");
                    break;
                case "updateauthorized"://授权变更
//                    this.disposeAuthResult(result);
                    logger.info("updateauthorized");
                    break;
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return CommonConstant.WECHAT_SUCCESS;
        }
        return CommonConstant.WECHAT_SUCCESS;
    }

    /**
     * 小程序第三方平台 回调处理
     */
    @ApiOperation(value = "小程序第三方平台回调", hidden = true)
    @GetMapping("/wechat/minipro/getOath2Url")
    public Object getOath2Url(@RequestBody WechatMiniProDto dto) {
        return getOath2Url(dto.getAppId(), uzaiConsoleSysConfig.getWxminiproRedirectUri(),false,dto.getMerId().toString()) ;
    }


    /**
     * 获取授权URL。
     * 第一步：用户同意授权，获取code;如果用户同意授权，页面附带code,state跳转至redirect_uri
     *
     * @param appId       公众号的唯一标识
     * @param redirectUri 授权后重定向的回调链接地址
     * ，在申请创建公众号服务成功后，可在公众号服务详情页找到
     * @return 授权URL@param detail      应用授权作用域:
     *      *                    false: snsapi_base;不弹出授权页面，直接跳转，只能获取用户openid.
     *      *                    true: snsapi_userinfo;弹出授权页面，可通过openid拿到昵称、性别、所在地.
     *      *                    并且，即使在未关注的情况下，只要用户授权，也能获取其信息.
     *      *      * @param state       重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节
     *      *      *                    服务方的appid
     */


    public  String getOath2Url(String appId, String redirectUri, boolean detail, String state) {
        StringBuilder sb = new StringBuilder();
        sb.append(Const.Uri.OPEN_URI + "/connect/oauth2/authorize?")
                .append("appid=").append(appId)
                .append("&redirect_uri=").append(UrlUtils.urlEncode(redirectUri))
                .append("&response_type=code")
                .append("&scope=").append(detail ? "snsapi_userinfo" : "snsapi_base")
                .append("&state=").append(state == null ? "" : state);
        sb.append("#wechat_redirect");
        return sb.toString();


//        https://mp.weixin.qq.com/cgi-bin/componentloginpage?component_appid=xxxx&pre_auth_code=xxxxx&redirect_uri=xxxx&auth_type=xxx&category_id_list=99|31

    }


    public static void main(String[] args) {
        String s = "mp1.uzaisoft.com/wx911d448d1c588510/callback";
        String state = "1306523192508030977" ;

        StringBuilder sb = new StringBuilder();
        sb.append(Const.Uri.OPEN_URI + "/connect/oauth2/authorize?")
                .append("appid=").append("wx911d448d1c588510")
                .append("&redirect_uri=").append(UrlUtils.urlEncode(s))
                .append("&response_type=code")
                .append("&scope=").append(true ? "snsapi_userinfo" : "snsapi_base")
                .append("&state=").append(state == null ? "" : state);
        sb.append("#wechat_redirect");
        System.out.println(sb.toString());

    }

}
